function ocp = acados_nmpc_ocp_get()
% This function
% Name          :acados_nmpc_ocp_get
% Descriptions  :设置ocp_opts和ocp_model，得到控制问题的控制对象ocp输入
% Return(s)     :ocp
% Author        :LHP,on April 2nd,2024

%% Problem formulation
    % 定义NMPC的参数
    N = 35;                                                     % 预测步长
    T = 21.0;                                                   % 预测总时长[s]

%% Solver parameters 
    compile_interface           = 'auto';                       % 编译接口设置 'auto'
    codgen_model                = 'true';                       % 代码生成模型设置 'true'
    compile_model               = 'true';                       % 代码编译模型设置 'true'
    
    nlp_solver                  = 'sqp';                        % sqp(更精确和稳定), sqp_rti(快但精度稍差) % 非线性规划求解器设置
    qp_solver                   = 'partial_condensing_hpipm';   % QP求解器设置
    nlp_solver_exact_hessian    = 'false';                      % 是否精确计算海森矩阵 false=gauss_newton, true=exact     
    qp_solver_cond_N            =  N;                           % 用于部分稠密化（partial condensing）情况下的新的优化问题的时间步数 5
    sim_method                  = 'erk';                        % 积分器类型设置：erk, irk, irk_gnsf

%% model dynamics
    model = acados_robot_model();                               % 使用差速移动机器人模型创建模型和约束
    nx = length(model.x);                                       % 状态变量数 5
    nu = length(model.u);                                       % 控制输入变量数 2
   
%% model to create the solver
    ocp_model = acados_ocp_model();                             % 创建OCP模型对象

%% acados ocp model
    ocp_model.set('name', model.name);                          % model name, used for code generation, default:  ocp_model 
    ocp_model.set('T', T);                                      % end time
                    
    % 设置符号变量
    ocp_model.set('sym_x', model.x);
    ocp_model.set('sym_u', model.u);
    ocp_model.set('sym_xdot', model.xdot);
    ocp_model.set('sym_p', model.p);

    % 设置运动学方程
    ocp_model.set('dyn_type', 'explicit');
    ocp_model.set('dyn_expr_f', model.f_expl_expr);
    
    % 设置约束
    ocp_model.set('constr_x0', zeros(nx,1));                    % 设置初始条件model.x0

    % 终端不变集约束
    %ocp_model.set('constr_expr_h', constraint.expr);     
    %ocp_model.set('constr_uh', 0);

    % Jbx映射x(t)到其边界向量
    Jbx = zeros(2,nx);
    Jbx(1,4) = 1;
    Jbx(2,5) = 1;
    % define upper and lower bounds on a subset of states
    ocp_model.set('constr_Jbx', Jbx);
    ocp_model.set('constr_lbx', [model.v_min, model.omega_min]);    % 设置控制变量 u(t) 的下界 tube中后续变化
    ocp_model.set('constr_ubx', [model.v_max, model.omega_max]);    % 设置控制变量 u(t) 的上界 tube中后续变化

    % 优化目标函数
    % ext_cost
%     cost_type = 'auto';                                           % auto, ext_cost, linear_ls, nonlinear_ls
%     ocp_model.set('cost_type', cost_type);
%     ocp_model.set('cost_type_e', cost_type);
    
    %ocp_model.set('cost_expr_ext_cost', model.cost_expr_ext_cost);
    %ocp_model.set('cost_expr_ext_cost_e', model.cost_expr_ext_cost_e);
    
    % nonlinear_ls
    cost_type = 'nonlinear_ls';                                     % auto, ext_cost, linear_ls, nonlinear_ls
    ocp_model.set('cost_type', cost_type);
    ocp_model.set('cost_type_e', cost_type);

    ocp_model.set('cost_expr_y', model.x);
    ocp_model.set('cost_expr_y_e', model.x);

    ocp_model.set('cost_W', model.W);                               % tube中后续变化:Q/P_nom
    ocp_model.set('cost_W_e', model.W_e);                           % 后续不会变

    % 设置初始参考
    ocp_model.set('cost_y_ref', model.y_ref);
    ocp_model.set('cost_y_ref_e', model.y_ref_e);

%% acados ocp set opts
    ocp_opts = acados_ocp_opts();                                       % 创建OCP选项对象
    %ocp_opts.set('compile_interface', compile_interface);
    %ocp_opts.set('codgen_model', codgen_model);
    %ocp_opts.set('compile_model', compile_model);
    ocp_opts.set('param_scheme_N', N);                                  % 描述离散化点的数量，通常用于将连续时间问题转化为离散时间问题
    ocp_opts.set('nlp_solver', nlp_solver);                             % 非线性规划求解器设置
    ocp_opts.set('nlp_solver_exact_hessian', nlp_solver_exact_hessian); % 是否精确计算海森矩阵
    ocp_opts.set('nlp_solver_max_iter', 200);
    ocp_opts.set('sim_method', sim_method);                             % 积分器类型设置
    ocp_opts.set('sim_method_num_stages', 4);                           % 数值积分方法阶数设置4
    ocp_opts.set('sim_method_num_steps', 5);                            % 数值积分方法步数设置5
    ocp_opts.set('qp_solver', qp_solver);                               % QP求解器设置
    ocp_opts.set('qp_solver_cond_N', qp_solver_cond_N);                 % 部分稠密化（partial condensing）情况下的新的优化问题的时间步数
    ocp_opts.set('qp_solver_iter_max', 200);
    ocp_opts.set('nlp_solver_tol_stat', 1e-4);                          % stopping criterion
    ocp_opts.set('nlp_solver_tol_eq', 1e-4);                            % stopping criterion
    ocp_opts.set('nlp_solver_tol_ineq', 1e-4);                          % stopping criterion
    ocp_opts.set('nlp_solver_tol_comp', 1e-4);                          % stopping criterion
    ocp_opts.set('parameter_values', zeros(nx,1));                      % 问题中状态变量的维度
    
%% create ocp solver
    ocp = acados_ocp(ocp_model, ocp_opts);                              % 创建OCP求解器对象 bug : Building templated code as shared library，只能运行一次

end